#include "ThreadCache.h"
#include "CentralCache.h"
void* ThreadCache::FetchFromCentralCache(size_t index, size_t bytes)
{
	size_t num = min(freeLists[index].MaxNum(), CalculateSize::NumMoveSize(bytes));
	if (freeLists[index].MaxNum() == num)
		freeLists[index].MaxNum() += 1;
	void* start = nullptr, * end = nullptr;
	size_t actualNum = CentralCache::GetInstance()->FetchRangeObj(start, end, num, bytes);
	if (actualNum == 1)
		return start;
	else
	{
		void* result = start;
		start = *(void**)start;
		freeLists[index].PushRange(start, end, actualNum - 1);
		return result;
	}
}
void* ThreadCache::Allocate(size_t bytes)
{
	size_t alignBytes = CalculateSize::GetBytes(bytes);
	size_t index = CalculateSize::GetIndex(bytes);

	if (freeLists[index].Empty() == true)
		return FetchFromCentralCache(index, alignBytes);
	else
		return freeLists[index].Pop();
}
void ThreadCache::ListTooLong(FreeList& freeList, size_t size)
{
	void* start = nullptr, * end = nullptr;
	freeList.PopRange(start, end, freeList.MaxNum());

	CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}
void ThreadCache::DeAllocate(void* ptr, size_t bytes)
{
	size_t index = CalculateSize::GetIndex(bytes);
	freeLists[index].Push(ptr);

	if (freeLists[index].Num() >= freeLists[index].MaxNum())
		ListTooLong(freeLists[index], bytes);
}